package com.spring.security.client.browser.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.security.core.properties.LoginResponseType;
import com.spring.security.core.properties.SecurityConstants;
import com.spring.security.core.properties.SecurityProperties;
import com.spring.security.core.support.ServerResponseEntity;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Strategy used to handle a successful user authentication.
 * <p>
 * Implementations can do whatever they want but typical behaviour would be to control the
 * navigation to the subsequent destination (using a redirect or a forward). For example,
 * after a user has logged in by submitting a login form, the application needs to decide
 * where they should be redirected to afterwards (see
 * {@link AbstractAuthenticationProcessingFilter} and subclasses). Other logic may also be
 * included if required.
 *
 * @author_seabed_moon
 */
@Log4j2
@Component("sunLandAuthenticationSuccessHandler")
public class SpringAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SecurityProperties securityProperties;

    private RequestCache requestCache = new HttpSessionRequestCache();

    /**
     * Called when a user has been successfully authenticated.
     *
     * @param httpServletRequest  the request which caused the successful authentication
     * @param httpServletResponse the response
     * @param authentication      the <tt>Authentication</tt> object which was created during
     *                            the authentication process.
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        logger.info("LOGIN SUCCESS ");
        if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginResponseType())) {
            httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            httpServletResponse.getWriter().write(objectMapper.writeValueAsString(ServerResponseEntity.success("", HttpStatus.OK.name())));
            String originHeader = httpServletRequest.getHeader("Origin");
            httpServletResponse.setHeader("Access-Control-Allow-Origin", originHeader);
            httpServletResponse.addHeader("Access-Control-Allow-Headers", SecurityConstants.DEFAULT_ACCESS_CONTROL_ALLOW_HEADERS);
            httpServletResponse.addHeader("Access-Control-Allow-Credentials", SecurityConstants.DEFAULT_ACCESS_CONTROL_ALLOW_CREDENTIALS);
            httpServletResponse.setHeader("Access-Control-Allow-Methods", SecurityConstants.DEFAULT_ACCESS_CONTROL_ALLOW_METHODS);
        } else {
            //是否配置了默认登录成功跳转页
            if (StringUtils.isNotBlank(securityProperties.getBrowser().getSingInSuccessUrl())) {
                requestCache.removeRequest(httpServletRequest, httpServletResponse);
                setAlwaysUseDefaultTargetUrl(true);
                setDefaultTargetUrl(securityProperties.getBrowser().getSingInSuccessUrl());
            } else {
                //跳转回登录前的页面
                SavedRequest savedRequest = requestCache.getRequest(httpServletRequest, httpServletResponse);
                httpServletResponse.sendRedirect(savedRequest.getRedirectUrl());
                return;
            }
            super.onAuthenticationSuccess(httpServletRequest, httpServletResponse, authentication);
        }
    }
}